/**
 *
 */
import React, { useContext, useRef, useState } from 'react';
import { Search } from '../../baseComponent';
import { BaseHelp, HelpContext, Table, TableSelectionModel, Tabs, type BaseHelpProps } from '../../functionalComponent';
import { compHoc, getGlobalConfig, Layout, TypeOmit, iup, useRefCallback, type IObject } from '../../util';
import { getHelpBeforeOpen } from './common';

const { Option } = Tabs;
const { Header, Footer, MultipleButtons } = BaseHelp;

const tableProps: any = {
  cache: false,
  headerMenu: false,
  style: { borderStyle: 'solid', borderColor: 'var(--border-color-split, #f0f0f0)', borderWidth: 1 }
};

function addDisabledProperty(data) {
  return data.map((item) => {
    if (item.children.length !== 0) {
      item.children = addDisabledProperty(item.children);
      return { ...item, disabled: true };
    } else {
      return item;
    }
  });
}

function HelpContent() {
  const {
    request,
    ok,
    contentParams: { getFieldValue, columns, helpTitle, typeCode, selectedArray, multiple, selectLeafOnly, footer },
    locale,
    randomKey
  } = useContext<any>(HelpContext);
  const btnRef = useRef<any>();
  const [activeKey, setActiveKey] = useState('0');
  const rightTable = useRef<any>();
  const getTable = () => iup.compIns[`${typeCode}_${randomKey}_${activeKey}`].getApi();

  const getResult: any = () => {
    if (multiple) {
      const result = rightTable.current
        .getApi()
        .getRows()
        .map((r) => ({
          value: getFieldValue(r),
          label: getFieldValue(r, 'label'),
          origin: { ...r }
        }));
      return result.length > 0 ? result : undefined;
    } else {
      const value = getTable().getSelectedData()[0];
      if (value) {
        return { value: getFieldValue(value), label: getFieldValue(value, 'label'), origin: { ...value } };
      }
      return undefined;
    }
  };
  const toRight = (values: any) => {
    if (multiple) {
      btnRef.current.toRight(values);
    } else {
      ok(getResult());
    }
  };

  const onSearch = (value: string) => {
    if (activeKey === '0') {
      getTable().query({ keyword: value });
    } else {
      getTable().filter(value);
    }
  };
  const tabTitle = (t) => <span style={{ padding: '0 8px' }}>{t}</span>;
  const tabBarExtraContent = (
    <Search size="small" allowClear placeholder={locale.searchPlaceholder} onSearch={onSearch} />
  );
  if (multiple) {
    tableProps.rowSelection = {
      type: [TableSelectionModel.CHECKBOX],
      autoCheckedChildren: false
    };
    tableProps.rowChecked = true;
    tableProps.rowSelected = false;
  } else {
    tableProps.rowSelection = undefined;
    tableProps.rowChecked = false;
    tableProps.rowSelected = true;
  }

  if (selectLeafOnly) {
    tableProps.rowSelection = {
      ...tableProps.rowSelection,
      disabled: (row) => row.children?.length
    };
  }

  // 设置选中列数据
  const setMultiTableData = (rows) => {
    const selected: any = [];
    const existValues = rightTable.current
      .getApi()
      .getRows()
      .map((r) => getFieldValue(r));
    rows.forEach((row, index) => {
      if (existValues.indexOf(getFieldValue(row)) === -1) {
        const newVal = JSON.parse(JSON.stringify(row));
        delete newVal.checked;
        // 排除父级节点
        if (!selectLeafOnly || !newVal?.children?.length) {
          selected.push(newVal);
        }
      }
    });
    rightTable.current.getApi().addRows(selected);
  };

  const renderTable = (index) => {
    return (
      <Table
        {...tableProps}
        isTree
        defaultExpand="all"
        style={{ ...tableProps.style, borderTopWidth: 0 }}
        id={`${typeCode}_${randomKey}_${index}`}
        columns={columns}
        onRow={(rowIndex, table) => ({
          onDoubleClick: () => toRight([table.getRow(rowIndex)])
        })}
        request={request}
      />
    );
  };

  return (
    <Layout>
      <Header title={helpTitle || '静态数据'} />
      <Layout.Flex direction="row" style={{ padding: '0 5px 5px 5px', borderBottom: 0 }}>
        <Layout.Flex flex={2}>
          <Tabs className="fit-height" size="small" onChange={setActiveKey} tabBarExtraContent={tabBarExtraContent}>
            <Option tab={tabTitle(locale.List)} key="0">
              <div style={{ height: '100%' }}>{renderTable(0)}</div>
            </Option>
          </Tabs>
        </Layout.Flex>
        {multiple && (
          <MultipleButtons
            addResult={(values) => setMultiTableData(values)}
            getRowKey={getFieldValue}
            outRef={btnRef}
            getActiveTable={getTable}
            getResultTable={() => rightTable.current.getApi()}
          />
        )}
        {multiple && (
          <Layout.Flex style={{ paddingTop: 7 }}>
            <Table
              {...tableProps}
              columns={columns}
              dataSource={selectedArray}
              ref={rightTable}
              onRow={(rowIndex) => ({
                onDoubleClick: () => btnRef.current.toLeft(rowIndex)
              })}
            />
          </Layout.Flex>
        )}
      </Layout.Flex>
      <Footer getResult={getResult}>{footer && <span style={{ flex: 1, width: 0 }} children={footer} />}</Footer>
    </Layout>
  );
}

export interface IStaticDicHelp extends BaseHelpProps {
  /**
   * 静态数据字段类型
   */
  typeCode: string;
  /**
   * 静态数据字段父级id
   */
  treePid?: string;
  /**
   * 静态数据的层级深度
   */
  level?: number;
  /**
   * @description       自定义弹出帮助的title
   */
  title: string;
  /**
   * @description       是否开启多选模式
   * @default           false
   */
  multiple?: boolean;
  /**
   * @description       是否只能选末级
   * @default           false
   */
  selectLeafOnly?: boolean;
  /**
   * @description       底部扩展组件
   */
  footer?: React.ReactNode;
  /**
   * @description       表格列配置
   */
  columns?: IObject[];
  /**
   * @description       获取焦点时即加载请求数据
   * @default           false
   */
  loadByFocus?: boolean;
  /**
   * @description       过滤条件{typeCode,treePid,level}
   */
  clientSqlFilter?: IObject | Function;
}

/**
 * 静态数据字典帮助
 */
export const StaticDicHelp = compHoc<IStaticDicHelp>((props) => {
  const cacheHelpInfo = useRef({ data: null, p: null });
  const {
    valueField = 'dataNo',
    labelField = 'title',
    userCodeField = 'dataNo',
    title,
    multiple = false,
    selectLeafOnly = false,
    modalProps,
    footer,
    modal = true,
    columns,
    onBeforeOpen,
    typeCode: tc,
    treePid,
    level,
    clientSqlFilter,
    ...others
  } = props;
  const otherProps: any = others;
  const typeCode = tc || otherProps.helpId;
  delete otherProps.helpId;
  const sqlFilter = useRefCallback(async () => {
    if (iup.isFunction(clientSqlFilter)) {
      return await clientSqlFilter();
    }
    return clientSqlFilter;
  });
  otherProps.onBeforeOpen = useRefCallback(async () => {
    const [status, helpInfo] = await getHelpBeforeOpen({ onBeforeOpen, cacheHelpInfo });
    if (iup.isObject(helpInfo)) {
      return helpInfo;
    }
    return status;
  });
  otherProps.request = useRefCallback(async ({ keyword }) => {
    const params = await sqlFilter();
    const data: any = {
      typeCode,
      treePid,
      level,
      filter: keyword?.trim?.() || '',
      ...params
    };
    keyword && (data.filter = keyword);
    const res = await iup.request.get({
      url: 'engine/simpleData/data/treeExt',
      data
    });
    if (res?.code === 0) return selectLeafOnly ? addDisabledProperty(res.data) : res?.data;
    return [];
  });
  otherProps.valueField = valueField;
  otherProps.userCodeField = userCodeField;
  otherProps.labelField = labelField;
  // 自定义modal弹出窗需要使用的参数
  otherProps.contentParams = {
    footer,
    typeCode,
    multiple,
    selectLeafOnly,
    valueField,
    labelField: otherProps.labelField,
    columns: columns ?? [
      { dataIndex: 'dataNo', title: '编码' },
      { dataIndex: 'title', title: '名称' }
    ]
  };
  if (title) {
    otherProps.contentParams.helpTitle = title;
  }
  otherProps.selectedRequest = useRefCallback(async ({ codes }) => {
    try {
      const { code, data } = await iup.request.body({
        url: '/engine/simpleData/data/getSimpleDataByTypeAndCodeList',
        skipError: true,
        data: { codeList: codes.split(','), typeCode }
      });
      return code === 0 ? data : [];
    } catch (e) {}
    return [];
  });
  if (onBeforeOpen) {
    otherProps.cache = false;
  }
  const { width, height } = getGlobalConfig().default.helpConfig;
  return (
    <BaseHelp
      {...otherProps}
      modal={modal}
      isTree
      helpContent={HelpContent}
      multiple={multiple}
      modalProps={{ width, height, ...modalProps }}
    />
  );
}, 'StaticDicHelp');

export const StaticDicHelpSelect = React.forwardRef<any, TypeOmit<IStaticDicHelp, 'footer' | 'modal' | 'multiple'>>(
  (props, ref) => {
    return <StaticDicHelp {...props} ref={ref} loadByFocus modal={false} multiple={false} />;
  }
);

export const MultipleStaticDicHelpSelect = React.forwardRef<
  any,
  TypeOmit<IStaticDicHelp, 'footer' | 'modal' | 'multiple'>
>((props, ref) => {
  return <StaticDicHelp {...props} ref={ref} loadByFocus modal={false} multiple />;
});
